// Локальные
#include "geometry/2d/geometry.h"
#include "fem/trianglenetsearch.h"

namespace fem
{
    //============================================================================================================================
    //============================================================================================================================
    TriangleNetSearch::TriangleNetSearch(int rect_per_row, int rect_per_column, double rect_width, double rect_height) :
        m_RectPerRow(rect_per_row), m_RectPerColumn(rect_per_column), m_RectangleWidth(rect_width), m_RectangleHeight(rect_height)
    {
        m_GridContent = new QList<int>*[m_RectPerColumn];
        for(int i = 0; i < m_RectPerColumn; i++)
            m_GridContent[i] = new QList<int>[m_RectPerRow];
    }

    //============================================================================================================================
    //============================================================================================================================
    TriangleNetSearch::~TriangleNetSearch()
    {
        for(int i = 0; i < m_RectPerColumn; i++)
            delete [] m_GridContent[i];
        delete [] m_GridContent;
    }

    //============================================================================================================================
    //============================================================================================================================
    void TriangleNetSearch::analyzeNet(const TriangleNet &net)
    {
        for(int i = 0; i < m_RectPerColumn; i++)
            for(int j = 0; j < m_RectPerRow; j++)
                m_GridContent[i][j].clear();

        for(int i = 0; i < net.numOfElements(); i++)
        {
            int min_rect_index_v;
            int max_rect_index_v;
            int min_rect_index_h;
            int max_rect_index_h;

            min_rect_index_v = qMin(net.point(i,0).x()/m_RectangleWidth, qMin(net.point(i,1).x()/m_RectangleWidth, net.point(i,2).x()/m_RectangleWidth));
            max_rect_index_v = qMax(net.point(i,0).x()/m_RectangleWidth, qMax(net.point(i,1).x()/m_RectangleWidth, net.point(i,2).x()/m_RectangleWidth));
            min_rect_index_h = qMin(net.point(i,0).y()/m_RectangleHeight, qMin(net.point(i,1).y()/m_RectangleHeight, net.point(i,2).y()/m_RectangleHeight));
            max_rect_index_h = qMax(net.point(i,0).y()/m_RectangleHeight, qMax(net.point(i,1).y()/m_RectangleHeight, net.point(i,2).y()/m_RectangleHeight));
            for(int j = min_rect_index_v; j <= max_rect_index_v; j++)
                for(int k = min_rect_index_h; k <= max_rect_index_h; k++)
                    if(!m_GridContent[k][j].contains(i))
                        m_GridContent[k][j].append(i);
        }

        m_PointMaterial.clear();
        m_PointMaterial.resize(net.numOfPoints());

        for(int i = 0; i < net.numOfElements(); i++)
            for(int j = 0; j < 3; j++)
                if(!m_PointMaterial[net.pointIndex(i, j)].contains(net.material(i)))
                    m_PointMaterial[net.pointIndex(i, j)].append(net.material(i));
    }

    //============================================================================================================================
    //============================================================================================================================
    int TriangleNetSearch::findTriangle(const TriangleNet &net, const geometry::_2d::Point &point) const
    {
        QList<int> rect_content = m_GridContent[(int)(point.y()/m_RectangleWidth)][(int)(point.x()/m_RectangleHeight)];

        for(int i = 0; i < rect_content.size(); i++)
        {
            geometry::_2d::Point A = net.point(rect_content[i], 0);
            geometry::_2d::Point B = net.point(rect_content[i], 1);
            geometry::_2d::Point C = net.point(rect_content[i], 2);
            geometry::_2d::Point Z = point;

            if(pointInsideTriangle(A, B, C, Z))
                return rect_content[i];
        }
        return -1;
    }
}
